# 代码编写者： 李朔
# 开发时间： 2021/7/11 11:17
import torch

# 数据集-训练集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

# 利用Tensor变量来存放我们的权重，这里我们的权重是一维的
w = torch.Tensor([1.0])
w.requires_grad = True  # 需要计算梯度,默认是不计算的


# model
def forward(x):
    # 因为w需要计算梯度，所以y=x*w中的y也需要梯度
    return x * w  # 这里w是一个tensor类型，这里x会被自动转换成tensor类型


# 损失函数
def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) ** 2


print("predict (before training)", 4, forward(4).item())
for epoch in range(100):
    for x, y in zip(x_data, y_data):
        l = loss(x, y)  # 前馈过程
        # 反馈过程，会自动的把整个计算链路上的梯度都求出来
        l.backward()  # w的梯度求完之后，计算图就释放了   这里就是计算的l关于w的偏导，也就是反馈过程
        print("\tgrad:", x, y, w.grad.item())
        # 修改权重数值，这里使用data不会建立计算图(计算图主要就是为了求梯度)
        w.data = w.data - 0.01 * w.grad.data
        # 将权重里面梯度的数据清零
        w.grad.data.zero_()

    print("progress:", epoch, l.item())

print("predict (after training)", 4, forward(4).item())
